package com.jk.service.quartz;

import com.jk.dao.quartz.QrtzTriggersDao;
import com.jk.dto.quartz.QrtzTriggersDTO;
import com.jk.entity.quartz.QrtzTriggers;
import com.jk.entity.quartz.ScheduleJob;
import com.jk.util.PageManager;
import com.jk.util.quartz.ConcurrentJob;
import com.jk.util.quartz.DisConcurrentJob;
import org.quartz.*;
import org.quartz.impl.JobDetailImpl;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * Created by yanghuan on 2016/1/21.
 */
@Service
public class QuartzService {

    @Autowired
    private Scheduler scheduler;
    @Autowired
    private QrtzTriggersDao qrtzTriggersDao;

    /**
     * 查询全部定时任务
     */
    public List<ScheduleJob> selectPage(QrtzTriggersDTO qrtzTriggersDTO) throws Exception {
        List<ScheduleJob> jobList = new ArrayList<ScheduleJob>();
        PageManager pageManager = new PageManager(qrtzTriggersDTO.getPage(), qrtzTriggersDTO.getRows());
        qrtzTriggersDTO.setPage(pageManager.getPage());
        qrtzTriggersDTO.setRows(pageManager.getPageSize());
        List<QrtzTriggers> qrtzTriggersList = qrtzTriggersDao.selectPage(qrtzTriggersDTO);
        for (QrtzTriggers qrtzTriggers : qrtzTriggersList) {
            ScheduleJob job = new ScheduleJob();
            job.setJobName(qrtzTriggers.getJobName());
            job.setJobGroupName(qrtzTriggers.getJobGroup());
            job.setTriggerName(qrtzTriggers.getTriggerName());
            job.setTriggerGroupName(qrtzTriggers.getTriggerGroup());
            selectJob(job);
            jobList.add(job);
        }
        return jobList;
    }

    public int pageCount(QrtzTriggersDTO query) throws DataAccessException {
        return qrtzTriggersDao.pageCount(query);
    }

    public ScheduleJob selectJob(ScheduleJob job) throws SchedulerException {
        JobKey jobKey = new JobKey(job.getJobName(), job.getJobGroupName());
        TriggerKey triggerKey = new TriggerKey(job.getTriggerName(), job.getTriggerGroupName());
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        Trigger trigger = scheduler.getTrigger(triggerKey);
        CronTriggerImpl cronTrigger = (CronTriggerImpl) trigger;
        job.setStartTime(cronTrigger.getStartTime());
        job.setEndTime(cronTrigger.getEndTime());
        job.setNextFireTime(cronTrigger.getNextFireTime());
        job.setPreviousFireTime(cronTrigger.getPreviousFireTime());
        job.setCronExpression(cronTrigger.getCronExpression());
        job.setIsNonConcurrent(jobDetail.isConcurrentExectionDisallowed());
        job.setJobStatus(scheduler.getTriggerState(trigger.getKey()).name());
        job.setDataMap(cronTrigger.getJobDataMap());
        job.setDesc(cronTrigger.getDescription());
        return job;
    }

    /**
     * 添加一个定时任务
     */
    public void addJob(ScheduleJob job) throws Exception {
        job.setJobName(UUID.randomUUID().toString());
        job.setJobGroupName("defaultJobGroup");
        Class<? extends Job> jobClass;
        if (job.getIsNonConcurrent()) {
            jobClass = DisConcurrentJob.class;
        } else {
            jobClass = ConcurrentJob.class;
        }
        JobDataMap jobDataMap = new JobDataMap();
        if (job.getDataMap() != null) {
            jobDataMap = new JobDataMap(job.getDataMap());
        }
        JobDetail jobDetail = JobBuilder.newJob(jobClass)
                .withIdentity(job.getJobName(), job.getJobGroupName())
                .build();
        CronTrigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(job.getTriggerName(), job.getTriggerGroupName())
                .startAt(job.getStartTime()).endAt(job.getEndTime())
                .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression()))
                .withDescription(job.getDesc())
                .usingJobData(jobDataMap)
                .build();
        scheduler.scheduleJob(jobDetail, trigger);
        scheduler.start();
    }

    /**
     * 修改一个任务的触发时间
     */
    public void saveJob(ScheduleJob job) throws Exception {
        JobKey jobKey = new JobKey(job.getJobName(), job.getJobGroupName());
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        if (jobDetail != null) {
            JobDetailImpl jobDetailImpl = (JobDetailImpl) jobDetail;
            if (job.getIsNonConcurrent()) {
                jobDetailImpl.setJobClass(DisConcurrentJob.class);
            } else {
                jobDetailImpl.setJobClass(ConcurrentJob.class);
            }
            scheduler.addJob(jobDetailImpl, true, true);
            QrtzTriggers qrtzTriggers = qrtzTriggersDao.selectByJobName(job.getJobName());
            TriggerKey triggerKey = new TriggerKey(qrtzTriggers.getTriggerName(), qrtzTriggers.getTriggerGroup());
            Trigger trigger = scheduler.getTrigger(triggerKey);
            CronTriggerImpl triggerImpl = (CronTriggerImpl) trigger;
            triggerImpl.setName(job.getTriggerName());
            triggerImpl.setGroup(job.getTriggerGroupName());
            triggerImpl.setStartTime(job.getStartTime());
            triggerImpl.setEndTime(job.getEndTime());
            triggerImpl.setCronExpression(job.getCronExpression());
            triggerImpl.setJobDataMap(new JobDataMap(job.getDataMap()));
            triggerImpl.setDescription(job.getDesc());
            scheduler.rescheduleJob(triggerKey, triggerImpl);
        } else {
            addJob(job);
        }
    }

    /**
     * 暂停
     */
    public void stopJob(ScheduleJob job) throws Exception {
        scheduler.pauseJob(new JobKey(job.getJobName(), job.getJobGroupName()));
    }

    /**
     * 恢复任务
     */
    public void resumeJob(ScheduleJob job) throws Exception {
        scheduler.resumeJob(new JobKey(job.getJobName(), job.getJobGroupName()));
    }

    /**
     * 立即执行一次任务
     */
    public void triggerJob(ScheduleJob job) throws Exception {
        scheduler.triggerJob(new JobKey(job.getJobName(), job.getJobGroupName()));
    }

    /**
     * 移除一个任务和触发器
     */
    public void deleteJob(ScheduleJob job) throws Exception {
        scheduler.pauseTrigger(new TriggerKey(job.getTriggerName(), job.getTriggerGroupName()));
        scheduler.unscheduleJob(new TriggerKey(job.getTriggerName(), job.getTriggerGroupName()));
        scheduler.deleteJob(new JobKey(job.getJobName(), job.getJobGroupName()));
    }

}
